#include <gtest/gtest.h>
#include <map>
#include <stdio.h>

#include "WinApiKernel.hpp"
#include "../../TestFunctions/src/TestFunctions.hpp"

class WinApiKernelTest : public ::testing::Test
{
protected:

	typedef int Integer;

	typedef std::vector<Integer>::const_iterator DataIterator;

	WinApiKernelTest() : _sizeArray(100000), _countIterations(100), _countThreads(16), _data(_sizeArray), _rnd(0.0f, _sizeArray), _query(&_winApiKernel), 
		_isRequered([&](const DataIterator& item){return *item > (_sizeArray / 2);}),
		_isNeedChanged([](const DataIterator& first, const DataIterator& second){return *first < *second;}){}

	void SetUp()
	{
		_winApiKernel.setCountThreads(_countThreads);
	}

	const Integer _sizeArray;
	const Integer _countIterations;
	const Integer _countThreads;

	std::vector<Integer> _data;

	KDM::math::Random<std::minstd_rand, Integer> _rnd;

	WinApiKernel<DataIterator> _winApiKernel;
	QDM::QueryDataManipulation<DataIterator> _query;

	std::function<bool (const DataIterator&)> _isRequered;
	std::function<bool (const DataIterator&, const DataIterator&)> _isNeedChanged;

	void fillData()
	{
		for (Integer i = 0; i < _sizeArray; i++)
		{
			_data[i] = _rnd();
		}
	}

	void clearData()
	{
		_data.clear();
	}
};


TEST_F(WinApiKernelTest, whereTest)
{
	fillData();
	testWhereFunction(_data, _query, _isRequered);
	clearData();
}

TEST_F(WinApiKernelTest, orderByTest)
{
	for (Integer j = 0; j < _countIterations; j++)
	{
		fillData();

		testOrderByFunction(_data, _query, _isNeedChanged);
	}

	clearData();
}

TEST_F(WinApiKernelTest, selectAndExecuteTest)
{
	typedef std::vector<float>::iterator FloatIterator;

	WinApiKernel<DataIterator, float> kernel;
	WinApiKernel<FloatIterator> executeKernel;

	kernel.setCountThreads(_countThreads);
	executeKernel.setCountThreads(_countThreads);

	fillData();

	testSelectAndExecuteFunctions(_data, kernel, executeKernel);

	clearData();
}

int main(int argc, char** argv)
{
	testing::InitGoogleTest(&argc, argv);
	RUN_ALL_TESTS();
	std::getchar(); // keep console window open until Return keystroke
}